#pragma once

#include <iostream>
#include <vector>
// #include <semaphore.h>
#include <pthread.h>
#include "sem.hpp"
#include "Mutex.hpp"

namespace ringBufferModule
{

    using namespace semModule;
    using namespace mutexModule;
    template <class T>
    class ringBuffer
    {

    public:
        ringBuffer(int cap) : _ring(cap), _cap(cap),
                              _p_step(0), _c_step(0),
                              _datasem(0), _spacesem(cap)
        {
            // 初始化环形缓冲区
            _ring.reserve(_cap);
            // pthread_mutex_init(&_p_lock, nullptr); // 初始化生产者锁
            // pthread_mutex_init(&_c_lock, nullptr); // 初始化消费者锁
        }
        ~ringBuffer()
        {
        }
        void equeue(const T &data)
        {
            // 生产者入队
            // std::cout << "Producing data: " << data << std::endl;
            _spacesem.P(); // 等待空间
            {
                LockGuard lockGuard(_p_lock); // 锁定生产者
                // zdl:: 怎么再这样的环节中体现生产和消费的形式
                _ring[_p_step] = data;          // 将数据放入环形缓冲区
                _p_step = (_p_step + 1) % _cap; // 更新生产}
            }
            _datasem.V();
        }
        void pop(T *out)
        {

            // 消费者的队列形式
            // zdl:: 本质上就是对资源的预定机制
            _datasem.P(); // 等待数据
            {
                LockGuard lockGuard(_c_lock);   // 锁定消费者
                *out = _ring[_c_step];          // 从环形缓冲区获取数据
                _c_step = (_c_step + 1) % _cap; // 更新消费者位置
            }
            _spacesem.V(); // 释放空间
        }

    private:
        std::vector<T> _ring; // 环   ，临界资源
        int _cap;             // 容量
        int _p_step;          // 生产者位置
        int _c_step;          // 消费者位置

        sem _datasem;  // 数据信号量
        sem _spacesem; // 空间信号量

        Mutex _p_lock;
        Mutex _c_lock;

    }; // namespace ringBufferModule
};
// 多生产多消费：
//  在进行这样的并发运行我们就需要维护生产者和消费者之间的多位关系
